﻿using com.uplus.common;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApi.Common
{
    /// <summary>
    /// 地图帮助类
    /// </summary>
    public class MapHelper
    {
        public static string ak = "527a36333f9ba0a28d59c560dabee8f6"; // 高德地图key
        public static string servicePath = "https://restapi.amap.com/v3";
        private const double x_pi = 3.14159265358979324 * 3000.0 / 180.0;

        /// <summary>
        /// 百度经纬度转高德经纬度
        /// </summary>
        /// <param name="lat">纬度</param>
        /// <param name="lon">经度</param>
        /// <returns></returns>
        public static double[] Baidu2GaodeMap(double lat, double lon)
        {

            try
            {
                if (lat != 0 && lon != 0)
                {
                    double var4 = 0.006401062D;
                    double var6 = 0.0060424805D;
                    double[] var2 = null;

                    for (int var3 = 0; var3 < 2; ++var3)
                    {
                        var2 = new double[2];
                        double var16 = lon - var4;
                        double var18 = lat - var6;
                        double[] var29 = new double[2];
                        double var24 = Math.Cos(b(var16) + Math.Atan2(var18, var16)) * (a(var18) + Math.Sqrt(var16 * var16 + var18 * var18)) + 0.0065D;
                        double var26 = Math.Sin(b(var16) + Math.Atan2(var18, var16)) * (a(var18) + Math.Sqrt(var16 * var16 + var18 * var18)) + 0.006D;
                        var29[1] = (c(var24));
                        var29[0] = (c(var26));
                        var2[1] = (c(lon + var16 - var29[1]));
                        var2[0] = (c(lat + var18 - var29[0]));
                        var4 = lon - var2[1];
                        var6 = lat - var2[0];
                    }

                    return var2;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return new double[] { lat, lon };
        }

        private static double a(double var0)
        {
            return Math.Sin(var0 * 3000.0D * (3.141592653589793D / 180.0D)) * 2.0E-5D;
        }

        private static double b(double var0)
        {
            return Math.Cos(var0 * 3000.0D * (3.141592653589793D / 180.0D)) * 3.0E-6D;
        }

        private static double c(double var0)
        {
            return Math.Round(var0, 8);
        }

        public static string Baidu2GaodeMapToString(double lat, double lon)
        {
            try
            {
                if (lat != 0 && lon != 0)
                {
                    double var4 = 0.006401062D;
                    double var6 = 0.0060424805D;
                    double[] var2 = null;

                    for (int var3 = 0; var3 < 2; ++var3)
                    {
                        var2 = new double[2];
                        double var16 = lon - var4;
                        double var18 = lat - var6;
                        double[] var29 = new double[2];
                        double var24 = Math.Cos(b(var16) + Math.Atan2(var18, var16)) * (a(var18) + Math.Sqrt(var16 * var16 + var18 * var18)) + 0.0065D;
                        double var26 = Math.Sin(b(var16) + Math.Atan2(var18, var16)) * (a(var18) + Math.Sqrt(var16 * var16 + var18 * var18)) + 0.006D;
                        var29[1] = (c(var24));
                        var29[0] = (c(var26));
                        var2[1] = (c(lon + var16 - var29[1]));
                        var2[0] = (c(lat + var18 - var29[0]));
                        var4 = lon - var2[1];
                        var6 = lat - var2[0];
                    }
                    return $"{var2[1]},{var2[0]}";
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return $"{lon},{lat}";
        }



        /// <summary>
        /// 地球半径
        /// </summary>
        private const double EarthRadius = 6378.137;


        /// <summary>
        /// 经纬度转化成弧度
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double Rad(double d)
        {
            return d * Math.PI / 180d;
        }


        /// <summary>
        /// 计算两个坐标点之间的距离
        /// </summary>
        /// <param name="firstLatitude">第一个坐标的纬度</param>
        /// <param name="firstLongitude">第一个坐标的经度</param>
        /// <param name="secondLatitude">第二个坐标的纬度</param>
        /// <param name="secondLongitude">第二个坐标的经度</param>
        /// <returns>返回两点之间的距离，单位：公里/千米</returns>
        public static double GetDistance(double firstLatitude, double firstLongitude, double secondLatitude, double secondLongitude)
        {
            var firstRadLat = Rad(firstLatitude);
            var firstRadLng = Rad(firstLongitude);
            var secondRadLat = Rad(secondLatitude);
            var secondRadLng = Rad(secondLongitude);


            var a = firstRadLat - secondRadLat;
            var b = firstRadLng - secondRadLng;
            var cal = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(firstRadLat)
                * Math.Cos(secondRadLat) * Math.Pow(Math.Sin(b / 2), 2))) * EarthRadius;
            var result = Math.Round(cal * 10000) / 10000;
            return result;
        }

        public static double GetDistance(string firstPoint, string secondPoint)
        {
            string result = "0";
            var firstArray = firstPoint.Split(',');
            var secondArray = secondPoint.Split(',');
            string url = "http://restapi.amap.com/v3/distance?key={0}&origins={1}&destination={2}&type=1";//高德
            string poiInfo = HttpMgr.GetData(string.Format(url, ak, firstPoint, secondPoint), "Utf-8");
            JObject jo = JObject.Parse(poiInfo);
            if (jo["status"].ToString() == "1")
            {
                JArray ja = JArray.Parse(jo["results"].ToString());

                result = ja[0]["distance"].ToString();
            }
            return Math.Round(Convert.ToDouble(result) / 1000, 0);
        }


        /// <summary>
        /// 计算两个坐标点之间的距离
        /// </summary>
        /// <param name="firstPoint">第一个坐标点的（纬度,经度）</param>
        /// <param name="secondPoint">第二个坐标点的（纬度,经度）</param>
        /// <returns>返回两点之间的距离，单位：公里/千米</returns>
        public static double GetPointDistance(string firstPoint, string secondPoint)
        {
            var firstArray = firstPoint.Split(',');
            var secondArray = secondPoint.Split(',');
            var firstLatitude = Convert.ToDouble(firstArray[1].Trim());
            var firstLongitude = Convert.ToDouble(firstArray[0].Trim());
            var secondLatitude = Convert.ToDouble(secondArray[1].Trim());
            var secondLongitude = Convert.ToDouble(secondArray[0].Trim());
            return GetDistance(firstLatitude, firstLongitude, secondLatitude, secondLongitude);
        }



        public static string Geocoder(string address)//输入地址返回经纬度
        {
            //string result = "39.92998577808024,116.39564503787867";
            string result = string.Empty;
            JObject json = new JObject();
            try
            {
                //string url = "http://api.map.baidu.com/geocoder/v2/?address={0}&output=json&ak={1}&callback=showLocation";//百度
                string url = "https://restapi.amap.com/v3/geocode/geo?address={0}&output=json&key={1}";//高德
                string poiInfo = HttpMgr.GetData(string.Format(url, address, ak), "Utf-8");
                #region 百度
                ////创建Get请求
                //url = string.Format(url, address, ak);
                //HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                //request.Method = "GET";
                //request.ContentType = "text/html;charset=UTF-8";

                ////接受返回来的数据
                //HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                //Stream stream = response.GetResponseStream();
                //StreamReader streamReader = new StreamReader(stream, Encoding.GetEncoding("utf-8"));
                //string retString = streamReader.ReadToEnd();
                //string str = retString.Substring(retString.IndexOf("(") + 1, retString.LastIndexOf(")") - retString.IndexOf("(") - 1);
                //JObject js = JObject.Parse(str);
                //str = js.Property("result").Value.ToString();
                //js = JObject.Parse(str);
                //str = js.Property("location").Value.ToString();

                //json = JObject.Parse(str);
                //result = json.Property("lat").Value.ToString() + "," + json.Property("lng").Value.ToString();
                //streamReader.Close();
                //stream.Close();
                //response.Close();
                #endregion

                #region 高德
                JObject jo = JObject.Parse(poiInfo);
                if (jo["status"].ToString() == "1")
                {
                    JArray ja = JArray.Parse(jo["geocodes"].ToString());

                    result = ja[0]["location"].ToString();
                }
                #endregion



                return result;
            }
            catch (Exception)
            {
                return result;
            }
        }

        public static double GetPointDistanceByAddress(string firstAddress, string secondAddress)//获取两个地址间距离
        {
            string firstpoint = Geocoder(firstAddress);
            string secondpoint = Geocoder(secondAddress);
            return Convert.ToDouble(GetPointDistance(firstpoint, secondpoint).ToString("0.0"));
        }

        public static double GetPointDistanceByAddress(string firstAddress, string lat, string lng)//获取两个地址间距离
        {
            string firstpoint = Geocoder(firstAddress);
            string secondpoint = string.Format("{0},{1}", lng, lat);
            //return Convert.ToDouble(GetPointDistance(firstpoint, secondpoint).ToString("0.0"));
            return Convert.ToDouble(GetDistance(firstpoint, secondpoint));

        }

        #region 作业路段起始点经纬度插值
        /// <summary>
        /// 作业路段起始点经纬度插值
        /// </summary>
        /// <param name="oldLongLat">路段经纬度集</param>
        /// <returns></returns>
        public static string LongLatInterpolation(string oldLongLat)
        {
            string re = "";
            string[] point = oldLongLat.Split(';');
            List<string> list = new List<string>();
            for (int i = 1; i < point.Length; i++)
            {
                string p1 = point[i - 1];
                string p2 = point[i];
                double newLongStep = (Convert.ToDouble(p2.Split(',')[0]) - Convert.ToDouble(p1.Split(',')[0])) / 8;
                double newLatStep = (Convert.ToDouble(p2.Split(',')[1]) - Convert.ToDouble(p1.Split(',')[1])) / 8;
                for (int j = 0; j < 9; j++)
                {
                    string newPoint = $"{Convert.ToDouble(p1.Split(',')[0]) + newLongStep * j},{Convert.ToDouble(p1.Split(',')[1]) + newLatStep * j}";
                    if (!list.Contains(newPoint))
                    {
                        list.Add(newPoint);
                    }

                }
            }
            foreach (string item in list)
            {
                re = re + item + ";";
            }
            return re.Trim(';');
        }
        #endregion

        #region 腾讯地图 转 百度地图
        /// <summary>
        ///  腾讯地图 转 百度地图
        /// </summary>
        /// <param name="lat">纬度</param>
        /// <param name="lng">经度</param>
        public static void txMap_to_bdMap(ref double lat, ref double lng)
        {
            double x = lng, y = lat;
            double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi);
            lng = z * Math.Cos(theta) + 0.0065;
            lat = z * Math.Sin(theta) + 0.006;
        }
        #endregion

        #region 百度地图 转 腾讯地图
        /// <summary>
        /// 百度地图 转 腾讯地图 /////////
        /// </summary>
        /// <param name="lat">纬度</param>
        /// <param name="lng">经度</param>
        public static void bdMap_to_txMap(ref double lat, ref double lng)
        {
            double x = lng - 0.0065, y = lat - 0.006;
            double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * x_pi);
            lng = z * Math.Cos(theta);
            lat = z * Math.Sin(theta);
        }
        #endregion
    }


}
